using CoreManager.Models.DTOs;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

namespace CoreManager.API.Common;

/// <summary>
/// 基础控制器，提供通用的返回值和用户信息获取功能
/// </summary>
[ApiController]
[Authorize] // 默认需要鉴权，子类可以通过[AllowAnonymous]覆盖
public abstract class BaseController : ControllerBase
{
    protected readonly ILogger Logger;

    protected BaseController(ILogger logger)
    {
        Logger = logger;
    }

    /// <summary>
    /// 获取当前请求的TraceId
    /// </summary>
    /// <returns>TraceId</returns>
    protected string GetTraceId()
    {

        return HttpContext?.Items["RequestId"]?.ToString() ?? string.Empty;
    }

    #region 统一返回结果方法

    /// <summary>
    /// 成功响应
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    /// <param name="data">数据</param>
    /// <param name="message">消息</param>
    /// <returns></returns>
    protected IActionResult Success<T>(T data, string message = "操作成功")
    {
        var traceId = GetTraceId();
        return Ok(ApiResponse<T>.Success(data, message, traceId));
    }

    /// <summary>
    /// 成功响应（无数据）
    /// </summary>
    /// <param name="message">消息</param>
    /// <returns></returns>
    protected IActionResult Success(string message = "操作成功")
    {
        var traceId = GetTraceId();
        return Ok(ApiResponse<object>.Success(null!, message, traceId));
    }

    /// <summary>
    /// 失败响应
    /// </summary>
    /// <param name="message">错误消息</param>
    /// <param name="code">错误码</param>
    /// <returns></returns>
    protected IActionResult Fail(string message, int code = 500)
    {
        var traceId = GetTraceId();
        return StatusCode(code, ApiResponse<object>.Fail(message, code, traceId));
    }

    /// <summary>
    /// 失败响应（带数据）
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    /// <param name="message">错误消息</param>
    /// <param name="code">错误码</param>
    /// <param name="data">数据</param>
    /// <returns></returns>
    protected IActionResult Fail<T>(string message, int code = 500, T? data = default)
    {
        var traceId = GetTraceId();
        return StatusCode(code, new ApiResponse<T>
        {
            Code = code,
            Message = message,
            Data = data,
            TraceId = traceId
        });
    }

    /// <summary>
    /// 参数验证失败响应
    /// </summary>
    /// <param name="message">错误消息</param>
    /// <returns></returns>
    protected IActionResult BadRequest(string message = "请求参数无效")
    {
        var traceId = GetTraceId();
        return base.BadRequest(ApiResponse<object>.Fail(message, 400, traceId));
    }

    /// <summary>
    /// 未找到资源响应
    /// </summary>
    /// <param name="message">错误消息</param>
    /// <returns></returns>
    protected IActionResult NotFound(string message = "资源不存在")
    {
        var traceId = GetTraceId();
        return base.NotFound(ApiResponse<object>.Fail(message, 404, traceId));
    }

    /// <summary>
    /// 未授权响应
    /// </summary>
    /// <param name="message">错误消息</param>
    /// <returns></returns>
    protected IActionResult Unauthorized(string message = "未授权访问")
    {
        var traceId = GetTraceId();
        return base.Unauthorized(ApiResponse<object>.Fail(message, 401, traceId));
    }

    /// <summary>
    /// 禁止访问响应
    /// </summary>
    /// <param name="message">错误消息</param>
    /// <returns></returns>
    protected IActionResult Forbidden(string message = "禁止访问")
    {
        var traceId = GetTraceId();
        return StatusCode(403, ApiResponse<object>.Fail(message, 403, traceId));
    }

    /// <summary>
    /// 服务器内部错误响应
    /// </summary>
    /// <param name="message">错误消息</param>
    /// <returns></returns>
    protected IActionResult InternalServerError(string message = "服务器内部错误")
    {
        var traceId = GetTraceId();
        return StatusCode(500, ApiResponse<object>.Fail(message, 500, traceId));
    }

    #endregion

    #region 用户信息获取方法

    /// <summary>
    /// 获取当前用户ID
    /// </summary>
    /// <returns>用户ID</returns>
    /// <exception cref="UnauthorizedAccessException">当无法获取用户ID时抛出</exception>
    protected int GetCurrentUserId()
    {
        var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier);
        if (userIdClaim == null || !int.TryParse(userIdClaim.Value, out int userId))
        {
            throw new UnauthorizedAccessException("无效的用户令牌");
        }

        return userId;
    }

    /// <summary>
    /// 获取当前用户ID（安全版本，不会抛出异常）
    /// </summary>
    /// <returns>用户ID，如果获取失败返回null</returns>
    protected int? GetCurrentUserIdSafe()
    {
        try
        {
            return GetCurrentUserId();
        }
        catch
        {
            return null;
        }
    }

    /// <summary>
    /// 获取当前用户名
    /// </summary>
    /// <returns>用户名</returns>
    protected string? GetCurrentUserName()
    {
        return User.FindFirst(ClaimTypes.Name)?.Value;
    }

    /// <summary>
    /// 获取当前用户角色
    /// </summary>
    /// <returns>用户角色列表</returns>
    protected List<string> GetCurrentUserRoles()
    {
        return User.FindAll(ClaimTypes.Role).Select(c => c.Value).ToList();
    }

    /// <summary>
    /// 获取当前用户的所有声明
    /// </summary>
    /// <returns>用户声明列表</returns>
    protected List<Claim> GetCurrentUserClaims()
    {
        return User.Claims.ToList();
    }

    /// <summary>
    /// 获取指定的用户声明值
    /// </summary>
    /// <param name="claimType">声明类型</param>
    /// <returns>声明值</returns>
    protected string? GetUserClaimValue(string claimType)
    {
        return User.FindFirst(claimType)?.Value;
    }

    #endregion

    #region 鉴权相关方法

    /// <summary>
    /// 检查当前用户是否具有指定角色
    /// </summary>
    /// <param name="role">角色名称</param>
    /// <returns>是否具有该角色</returns>
    protected bool HasRole(string role)
    {
        return User.IsInRole(role);
    }

    /// <summary>
    /// 检查当前用户是否具有指定角色之一
    /// </summary>
    /// <param name="roles">角色名称列表</param>
    /// <returns>是否具有任一角色</returns>
    protected bool HasAnyRole(params string[] roles)
    {
        return roles.Any(role => User.IsInRole(role));
    }

    /// <summary>
    /// 检查当前用户是否具有指定权限
    /// </summary>
    /// <param name="permission">权限名称</param>
    /// <returns>是否具有该权限</returns>
    protected bool HasPermission(string permission)
    {
        return User.HasClaim("Permission", permission);
    }

    /// <summary>
    /// 检查当前用户是否具有指定权限之一
    /// </summary>
    /// <param name="permissions">权限名称列表</param>
    /// <returns>是否具有任一权限</returns>
    protected bool HasAnyPermission(params string[] permissions)
    {
        return permissions.Any(permission => User.HasClaim("Permission", permission));
    }

    /// <summary>
    /// 检查当前用户是否已认证
    /// </summary>
    /// <returns>是否已认证</returns>
    protected bool IsAuthenticated()
    {
        return User.Identity?.IsAuthenticated == true;
    }

    /// <summary>
    /// 要求用户具有指定角色，否则返回403
    /// </summary>
    /// <param name="role">角色名称</param>
    /// <returns>如果具有角色返回null，否则返回403响应</returns>
    protected IActionResult? RequireRole(string role)
    {
        return !HasRole(role) ? Forbidden($"需要角色: {role}") : null;
    }

    /// <summary>
    /// 要求用户具有指定权限，否则返回403
    /// </summary>
    /// <param name="permission">权限名称</param>
    /// <returns>如果具有权限返回null，否则返回403响应</returns>
    protected IActionResult? RequirePermission(string permission)
    {
        return !HasPermission(permission) ? Forbidden($"需要权限: {permission}") : null;
    }

    #endregion

    #region 异常处理

    /// <summary>
    /// 处理异常并返回适当的响应
    /// </summary>
    /// <param name="ex">异常</param>
    /// <param name="operation">操作描述</param>
    /// <returns>错误响应</returns>
    protected IActionResult HandleException(Exception ex, string operation = "操作")
    {
        var traceId = GetTraceId();
        Logger.LogError(ex, "{operation}失败，TraceId: {traceId}", operation, traceId);
        return ex switch
        {
            UnauthorizedAccessException => Unauthorized(ex.Message),
            ArgumentNullException => BadRequest(ex.Message),
            ArgumentException => BadRequest(ex.Message),
            InvalidOperationException => BadRequest(ex.Message),
            _ => InternalServerError($"{operation}失败，请稍后重试")
        };
    }

    /// <summary>
    /// 执行操作并处理异常
    /// </summary>
    /// <typeparam name="T">返回数据类型</typeparam>
    /// <param name="operation">操作</param>
    /// <param name="operationName">操作名称</param>
    /// <returns>操作结果或错误响应</returns>
    protected async Task<IActionResult> ExecuteAsync<T>(Func<Task<T>> operation, string operationName = "操作")
    {
        try
        {
            var result = await operation();
            return Success(result);
        }
        catch (Exception ex)
        {
            return HandleException(ex, operationName);
        }
    }

    /// <summary>
    /// 执行操作并处理异常（无返回值）
    /// </summary>
    /// <param name="operation">操作</param>
    /// <param name="operationName">操作名称</param>
    /// <returns>操作结果或错误响应</returns>
    protected async Task<IActionResult> ExecuteAsync(Func<Task> operation, string operationName = "操作")
    {
        try
        {
            await operation();
            return Success();
        }
        catch (Exception ex)
        {
            return HandleException(ex, operationName);
        }
    }

    #endregion

    #region 分页相关

    /// <summary>
    /// 创建分页响应
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    /// <param name="items">数据列表</param>
    /// <param name="total">总记录数</param>
    /// <param name="pageIndex">当前页码</param>
    /// <param name="pageSize">每页大小</param>
    /// <returns>分页响应</returns>
    protected IActionResult PagedResult<T>(List<T> items, int total, int pageIndex, int pageSize)
    {
        var result = new PagedResponse<T>
        {
            Items = items,
            Total = total,
            PageIndex = pageIndex,
            PageSize = pageSize
        };
        return Success(result);
    }

    #endregion
}